package queue_sim

import "gitee.com/tfcolin/dsg"
import "math/rand"

func ServiceSimulate (custom_time [][]float64, si * ServiceInfo) ServiceSimulationResult {

	ns := si.ns
	var load []int = make ([]int, ns) 
	var qlen []int = make ([]int, ns) 

	var sig ServiceSignal
	var st  ServiceStatus
	var res ServiceSimulationResult = make ([]ServiceStatus, 0)

	var sigq * dsg.PQueue = dsg.InitPQueue (ServiceStatusCompFunc)

	for i := 0; i < ns; i ++ {
		for _, t := range custom_time[i] {
			sig.sid = i
			sig.time = t
			sig.updown = 1
			sigq.Add (sig)
		}
	}

	for ;sigq.GetSize() != 0; {
		sig = sigq.Pop().(ServiceSignal)
		id := sig.sid
		time := sig.time
		if (sig.updown == 1) {
			var obj int
			tprob := si.trans (id, qlen)
			u := rand.Float64()
			var tdist float64
			for obj = 0; obj < ns; obj ++ {
				tdist += tprob[obj]
				if (u < tdist) { 
					break 
				}
			}
			if (obj == ns) {obj = id}
			// obj = id
			if (load[obj] < si.num_su[obj]) {
				load[obj] ++
				sig.sid = obj
				sig.time += si.timer (obj)
				sig.updown = -1
				sigq.Add (sig)
			} else {
				qlen[obj] ++
			}
		} else {
			if (qlen[id] > 0) {
				qlen[id] -- 
				sig.time += si.timer (id)
				sig.updown = -1
				sigq.Add (sig)
			} else {
				load[id] --
			}
		}
		st.Init (ns)
		st.time = time
		copy (st.qlen, qlen)
		copy (st.load, load)
		res = append (res, st)
	}
	return res
}

func (ssres ServiceSimulationResult) ShowServiceSimulation (ui ServiceSimulationUI) {

	nst := len(ssres)
	end_time := ssres.GetEndTime()

	ui.SimulationStart()

	for i := 0; i < nst; i ++ {
		if (i < nst - 1) {
			ui.ShowStatus (ssres[i], ssres[i + 1].time)
		} else {
			ui.ShowStatus (ssres[i], end_time)
		}
	}

	ui.SimulationEnd()
}

